//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <ddk.h>
#include "gpio.h"

typedef struct {
    unsigned long gpin;
    unsigned long direct;/*0: in, 1: out*/
    unsigned long level;/**/
    unsigned long altfn;
}sGPIO_TBL;

sGPIO_TBL GPIO[] = {
/* GPIO PIN NAME		DIRECT LEVEL    ALTFUNC*/ // PIN#
    {GPIO_P_PHONE_INT,      0,  0,      0},     //0
    {GPIO_P_PEN_INT,        0,  0,      0},     //1
    {GPIO_P_SYS_EN,         0,  0,      0},     //2
    {GPIO_P_SW_INT,         0,  0,      0},     //3
    {GPIO_P_USB_PLUGIN,     0,  0,      0},     //4
    {GPIO_PWR_CAP0,         0,  0,      0},     //5
    {GPIO_PWR_CAP1,         0,  0,      0},     //6
    {GPIO_PWR_CAP2,         0,  0,      0},     //7
    {GPIO_PWR_CAP3,         0,  0,      0},     //8
    {GPIO_P_LINECONTROL,    0,  0,      0},     //9
    {GPIO_P_CLK_TOUT,       1,  0,      3},     //10
    {GPIO_FLASH_ENB,        1,  0,      0},     //11
    {GPIO_P_SD_PLUGIN,      0,  0,      0},     //12
    {GPIO_P_USB_ID,         0,  0,      0},     //13
    {GPIO_P_SSPDAV,         0,  0,      0},     //14?
    {GPIO_EMPTY1,           1,  0,      0},     //15
    {GPIO_P_PWMOUT0,        1,  0,      0},     //16
    {GPIO_P_CIF_DD6,        0,  0,      2},     //17
    {GPIO_P_KEY_BACKLIGHT,  1,  0,      0},     //18
    {GPIO_P_LCD_RST,        1,  0,      0},     //19
    {GPIO_P_SDCS2,          1,  0,      1},     //20
    {GPIO_EMPTY2,           1,  0,      0},     //21
    {GPIO_P_CAMERA_RST,     1,  0,      0},     //22
    {GPIO_P_SSPSCLK,        1,  0,      2},     //23
    {GPIO_P_SSPFRAM,        1,  0,      2},     //24
    {GPIO_P_SSPTXD,         1,  0,      2},     //25
    {GPIO_P_SSPRXD,         0,  0,      1},     //26
    {GPIO_P_SPKPA_SHUTDOWN, 1,  0,      0},     //27
    {GPIO_P_AC97_BITCLK,    1,  0,      1},     //28
    {GPIO_P_AC97_SDATA_IN,  0,  0,      2},     //29
    {GPIO_P_AC97_SDATA_OUT, 1,  0,      1},     //30
    {GPIO_P_AC97_SYNC,      1,  0,      1},     //31
    {GPIO_P_SDIO_CLK,       1,  0,      2},     //32
    {GPIO_EMPTY3,           1,  0,      0},     //33
    {GPIO_P_FFRXD,          0,  0,      1},     //34
    {GPIO_P_FFCTS,          0,  0,      1},     //35
    {GPIO_P_VIBRATION,      1,  0,      0},     //36
    {GPIO_P_FFDSR,          0,  0,      1},     //37
    {GPIO_P_FFRI,           0,  0,      0},     //38
    {GPIO_P_FFTXD,          1,  0,      2},     //39
    {GPIO_P_FFDTR,          1,  0,      2},     //40
    {GPIO_P_FFRTS,          1,  0,      2},     //41
    {GPIO_P_BTRXD,          0,  0,      1},     //42
    {GPIO_P_BTTXD,          1,  0,      2},     //43
    {GPIO_P_PWM_G,          1,  0,      0},     //44
    {GPIO_P_EARPA_UPDN,     1,  0,      0},     //45
    {GPIO_P_ICP_RXD,        0,  0,      2},     //46
    {GPIO_P_ICP_TXD,        1,  0,      1},     //47
    {GPIO_P_CIF_DD5,        0,  0,      1},     //48
    {GPIO_EMPTY4,           1,  0,      0},     //49
    {GPIO_P_CIF_DD3,        0,  0,      1},     //50
    {GPIO_P_CIF_DD2,        0,  0,      1},     //51
    {GPIO_P_CIF_DD4 ,       0,  0,      1},     //52
    {GPIO_P_CIF_MCLK ,      1,  0,      2},     //53
    {GPIO_P_CIF_PCLK,       0,  0,      3},     //54
    {GPIO_P_CIF_DD1,        0,  0,      1},     //55
    {GPIO_P_MIC_CHOICE,     1,  0,      0},     //56
    {GPIO_IRDA_ENB,         1,  1,      0},     //57
    {GPIO_P_L_DD0,          0,  0,      2},     //58
    {GPIO_P_L_DD1,          0,  0,      2},     //59
    {GPIO_P_L_DD2,          0,  0,      2},     //60
    {GPIO_P_L_DD3,          0,  0,      2},     //61
    {GPIO_P_L_DD4,          0,  0,      2},     //62
    {GPIO_P_L_DD5,          0,  0,      2},     //63
    {GPIO_P_L_DD6,          0,  0,      2},     //64
    {GPIO_P_L_DD7,          0,  0,      2},     //65
    {GPIO_P_L_DD8,          0,  0,      2},     //66
    {GPIO_P_L_DD9,          0,  0,      2},     //67
    {GPIO_P_L_DD10,         0,  0,      2},     //68
    {GPIO_P_L_DD11,         0,  0,      2},     //69
    {GPIO_P_L_DD12,         0,  0,      2},     //70
    {GPIO_P_L_DD13,         0,  0,      2},     //71
    {GPIO_P_L_DD14,         0,  0,      2},     //72
    {GPIO_P_L_DD15,         0,  0,      2},     //73
    {GPIO_P_L_FCLK,         1,  0,      2},     //74
    {GPIO_P_L_LCLK,         1,  0,      2},     //75
    {GPIO_P_L_PCLK,         1,  0,      2},     //76
    {GPIO_P_FM_ENABLE,      1,  0,      0},     //77
    {GPIO_EMPTY5,           1,  0,      0},     //78
    {GPIO_P_CAMERA_SHDN ,   1,  1,      0},     //79
    {GPIO_P_LCD_RSB,        1,  0,      0},     //80
    {GPIO_P_CIF_DD0,        0,  0,      2},     //81
    {GPIO_LCD_PWRENB,       1,  0,      0},     //82
    {GPIO_CAMERA_PWRENB,    1,  0,      0},     //83
    {GPIO_P_CIF_FV,         0,  0,      3},     //84
    {GPIO_P_CIF_LV,         0,  0,      3},     //85
    {GPIO_P_L_DD16,         1,  0,      2},     //86
    {GPIO_P_L_DD17,         1,  0,      2},     //87
    {GPIO_USBHPWR1,         0,  0,      0},     //88
    {GPIO_P_AMP_PWRENB,     1,  1,      0},     //89
    {GPIO_P_EARPA_CLK,      1,  0,      0},     //90
    {GPIO_P_PWM_B,          1,  0,      0},     //91
    {GPIO_P_SDIO_DAT0,      0,  0,      1},     //92
    {GPIO_P_ONKEY,          0,  0,      1},     //93
    {GPIO_P_L_CS,           1,  0,      0},     //94
    {GPIO_P_L_SCL,          1,  0,      0},     //95
    {GPIO_P_L_SI,           1,  0,      0},     //96
    {GPIO_P_KP_MKIN3,       0,  0,      3},     //97
    {GPIO_P_KP_MKIN4,       0,  0,      0},     //98
    {GPIO_VBUS_ENB,         1,  0,      0},     //99
    {GPIO_P_KP_MKIN0,       0,  0,      1},     //100
    {GPIO_P_KP_MKIN1,       0,  0,      1},     //101
    {GPIO_P_KP_MKIN2,       0,  0,      1},     //102
    {GPIO_P_KP_MKOUT0,      1,  0,      2},     //103
    {GPIO_P_KP_MKOUT1,      1,  0,      2},     //104
    {GPIO_P_KP_MKOUT2,      1,  0,      2},     //105
    {GPIO_P_KP_MKOUT3,      0,  0,      0},     //106
    {GPIO_P_KP_MKOUT4,      0,  0,      0},     //107
    {GPIO_P_CIF_DD7,        0,  0,      1},     //108
    {GPIO_P_SDIO_DAT1,      0,  0,      1},     //109
    {GPIO_P_SDIO_DAT2,      0,  0,      1},     //110
    {GPIO_P_SDIO_DAT3,      0,  0,      1},     //111
    {GPIO_P_SDIO_CMD,       0,  0,      1},     //112
    {GPIO_P_AC97_RST,       1,  0,      1},     //113
    {GPIO_P_PWM_R,          1,  0,      0},     //114
    {GPIO_FLASH_CONTROL,    1,  0,      0},     //115
    {GPIO_VCC_CORE_1,       1,  1,      0},     //116
    {GPIO_P_I2C_SCL,        1,  0,      1},     //117
    {GPIO_P_I2C_SDA,        0,  0,      1},     //118
    {GPIO_USBHPWR2,         1,  0,      0},     //119
    {GPIO_VCC_CORE_2,       1,  0,      0},     //120
};

void GPIO_Reset()
{
    GPIO_REGS * pGPIO = (GPIO_REGS *)0x80E00000;
    for (unsigned int i = 0; i < sizeof(GPIO)/sizeof(sGPIO_TBL); i++) {
        volatile unsigned long *pGPLR = &pGPIO->GPLR0;
        volatile unsigned long *pGPDR = &pGPIO->GPDR0;
        volatile unsigned long *pGPCR = &pGPIO->GPCR0;
        volatile unsigned long *pGPSR = &pGPIO->GPSR0;
        volatile unsigned long *pGAFR = &pGPIO->GAFR0_L;

        kprintf("[%d]:\t%d\t%d\t%d\n", GPIO[i].gpin, GPIO[i].direct, GPIO[i].level, GPIO[i].altfn);

        if (i >= 96) {
            pGPLR = &pGPIO->GPLR3;
            pGPDR = &pGPIO->GPDR3;
            pGPSR = &pGPIO->GPSR3;
            pGPCR = &pGPIO->GPCR3;
        }

        int x = GPIO[i].gpin >> 4;
        int y = (GPIO[i].gpin & 0x0f) << 1;

        pGAFR[x] &= ~(3 << y);
        pGAFR[x] |= (GPIO[i].altfn << y);

        kprintf("alt x=%d, y=%d, %08x\t", x, y, (GPIO[i].altfn << y));
//        kprintf("GAFR [%08x] = %08x\n", &pGAFR[x], pGAFR[x]);

        x = GPIO[i].gpin >> 5;
        y = GPIO[i].gpin & 0x1f;

        if (GPIO[i].direct == 0) {//In
            pGPDR[x] &= ~(0x1 << y);
        }
        else {//Out
            if (GPIO[i].level == 0) {//Low
                pGPCR[x] = (0x1 << y);
            }
            else {//High
                pGPSR[x] = (0x1 << y);
            }

            pGPDR[x] |= (0x1 << y);
        }

        kprintf("x=%d, y=%d, %08x\n", x, y, (0x1 << y));
//        kprintf("GPDR [%08x] = %08x, GPLR [%08x] = %08x\n",
//            &pGPDR[x], pGPDR[x], &pGPLR[x], pGPLR[x]);

    }
    return ;
}

void GPIO_Reset2()
{
//    unsigned long pGPLR[4] = {0, 0, 0, 0};
    unsigned long pGPDR[4] = {0, 0, 0, 0};
    unsigned long pGPSR[4] = {0, 0, 0, 0};
    unsigned long pGPCR[4] = {0, 0, 0, 0};
    unsigned long pGAFR[8] = {0, 0, 0, 0, 0, 0, 0, 0};

    for (unsigned int i = 0; i < sizeof(GPIO)/sizeof(sGPIO_TBL); i++) {
//        kprintf("[%d]:\t%d\t%d\t%d\n", GPIO[i].gpin, GPIO[i].direct, GPIO[i].level, GPIO[i].altfn);

        int x = GPIO[i].gpin >> 4;
        int y = (GPIO[i].gpin & 0x0f) << 1;

        pGAFR[x] &= ~(3 << y);
        pGAFR[x] |= (GPIO[i].altfn << y);

//        kprintf("alt x=%d, y=%d, %08x\t", x, y, (GPIO[i].altfn << y));
//        kprintf("GAFR [%08x] = %08x\n", &pGAFR[x], pGAFR[x]);

        x = GPIO[i].gpin >> 5;
        y = GPIO[i].gpin & 0x1f;

        if (GPIO[i].direct == 0) {//In
            pGPDR[x] &= ~(0x1 << y);
        }
        else {//Out
            if (GPIO[i].level == 0) {//Low
                pGPCR[x] |= (0x1 << y);
            }
            else {//High
                pGPSR[x] |= (0x1 << y);
            }

            pGPDR[x] |= (0x1 << y);
        }

//       kprintf("x=%d, y=%d, %08x\n", x, y, (0x1 << y));
//        kprintf("GPDR [%08x] = %08x, GPLR [%08x] = %08x\n",
//            &pGPDR[x], pGPDR[x], &pGPLR[x], pGPLR[x]);

    }

    GPIO_REGS * pGPIO = (GPIO_REGS *)0x80E00000;
    pGPIO->GAFR0_L = pGAFR[0];
    pGPIO->GAFR0_U = pGAFR[1];
    pGPIO->GAFR1_L = pGAFR[2];
    pGPIO->GAFR1_U = pGAFR[3];
    pGPIO->GAFR2_L = pGAFR[4];
    pGPIO->GAFR2_U = pGAFR[5];
    pGPIO->GAFR3_L = pGAFR[6];
    pGPIO->GAFR3_U = pGAFR[7];

    pGPIO->GPCR0 = pGPCR[0];
    pGPIO->GPCR1 = pGPCR[1];
    pGPIO->GPCR2 = pGPCR[2];
    pGPIO->GPCR3 = pGPCR[3];

    pGPIO->GPSR0 = pGPSR[0];
    pGPIO->GPSR1 = pGPSR[1];
    pGPIO->GPSR2 = pGPSR[2];
    pGPIO->GPSR3 = pGPSR[3];

    pGPIO->GPDR0 = pGPDR[0];
    pGPIO->GPDR1 = pGPDR[1];
    pGPIO->GPDR2 = pGPDR[2];
    pGPIO->GPDR3 = pGPDR[3];

    return ;
}

void GPIO_ResetAll()
{
    GPIO_REGS * pGPIO = (GPIO_REGS *)0x80E00000;
    pGPIO->GAFR0_L = 0x00000000;
    pGPIO->GAFR0_U = 0x00000000;
    pGPIO->GAFR1_L = 0x00000000;
    pGPIO->GAFR1_U = 0x00000000;
    pGPIO->GAFR2_L = 0x00000000;
    pGPIO->GAFR2_U = 0x00000000;
    pGPIO->GAFR3_L = 0x00000000;
    pGPIO->GAFR3_U = 0x00000000;

    pGPIO->GPCR0 = 0xffffffff;
    pGPIO->GPCR1 = 0xffffffff;
    pGPIO->GPCR2 = 0xffffffff;
    pGPIO->GPCR3 = 0x00ffffff;

    pGPIO->GPDR0 = 0;//0xffffffff;
    pGPIO->GPDR1 = 0;//0xffffffff;
    pGPIO->GPDR2 = 0;//0xffffffff;
    pGPIO->GPDR3 = 0;//0x00ffffff;

    return ;
}
